﻿#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
using namespace std;

template <class ...Args>
void Print(Args&&... args)
{
	cout << sizeof...(args) << endl;
}
//int main()
//{
//	double x = 2.2;
//	Print(); // 包里有0个参数
//	Print(1); // 包里有1个参数
//	Print(1, string("xxxxx")); // 包里有2个参数
//	Print(1.1, string("xxxxx"), x); // 包里有3个参数
//	return 0;
//}

// 原理1：编译本质这里会结合引用折叠规则实例化出以下四个函数
void Print();
void Print(int&& arg1);
void Print(int&& arg1, string&& arg2);
void Print(double&& arg1, string&& arg2, double& arg3);

// 原理2：更本质去看没有可变参数模板，我们实现出这样的多个函数模板才能支持
// 这里的功能，有了可变参数模板，我们进一步被解放，他是类型泛化基础
// 上叠加数量变化，让我们泛型编程更灵活。
void Print();

template <class T1>
void Print(T1&& arg1);

template <class T1, class T2>
void Print(T1&& arg1, T2&& arg2);

template <class T1, class T2, class T3>
void Print(T1&& arg1, T2&& arg2, T3&& arg3);
// ...

template <class ...Args>
void Print(Args... args)
{
	 // 可变参数模板编译时解析
	 // 下面是运行获取和解析，所以不支持这样用
	 cout << sizeof...(args) << endl;
	 for (size_t i = 0; i < sizeof...(args); i++)
	 {
		 cout << args[i] << " ";
	 }
	 cout << endl;
}
int main()
{
	Print();
	Print(1);
	Print(1, string("xxxxx"));
	Print(1, string("xxxxx"), 2.2);
	return 0;
}


void ShowList()
{
	// 编译器时递归的终止条件，参数包是0个时，直接匹配这个函数
	cout << endl;
}
template <class T, class ...Args>
void ShowList(T x, Args... args)
{
	cout << x << " ";
	// args是N个参数的参数包
	// 调用ShowList，参数包的第一个传给x，剩下N-1传给第二个参数包
	ShowList(args...);
}
// 编译时递归推导解析参数
template <class ...Args>
void Print(Args... args)
{
	ShowList(args...);
}
int main()
{
	Print();
	Print(1);
	Print(1, string("xxxxx"));
	Print(1, string("xxxxx"), 2.2);
	return 0;
}

template <class T, class ...Args>
void ShowList(T x, Args... args)
{
	cout << x << " ";
	Print(args...);
}
 //Print(1, string("xxxxx"), 2.2);调用时
 //本质编译器将可变参数模板通过模式的包扩展，编译器推导的以下三个重载函数函数
void ShowList(double x)
{
	cout << x << " ";
	ShowList();
}

void ShowList(string x, double z)
{
	cout << x << " ";
	ShowList(z);
}

void ShowList(int x, string y, double z)
{
	cout << x << " ";
	ShowList(y, z);
}
void Print(int x, string y, double z)
{
	ShowList(x, y, z);
}


template <class T>
const T& GetArg(const T& x)
{
	cout << x << " ";
	return x;
}

template <class ...Args>
void Arguments(Args... args)
{}

template <class ...Args>
void Print(Args... args)
{
	// 注意GetArg必须返回或者到的对象，这样才能组成参数包给Arguments
	Arguments(GetArg(args)...);
}
// 本质可以理解为编译器编译时，包的扩展模式
// 将上面的函数模板扩展实例化为下面的函数
void Print(int x, string y, double z)
{
	Arguments(GetArg(x), GetArg(y), GetArg(z));
}

int main()
{
	Print(1, string("xxxxx"), 2.2);
	return 0;
}


#include<list>
#include"string.h"
// emplace_back总体而言是更高效，推荐以后使用emplace系列替代insert和push系列
int main()
{
	list<zyb::string> lt;//对象参数为单参数时的场景

	// 传左值，跟push_back一样，走拷贝构造
	zyb::string s1("111111111111");
	lt.emplace_back(s1);
	cout << "*********************************" << endl;

	// 右值，跟push_back一样，走移动构造
	lt.emplace_back(move(s1));
	cout << "*********************************" << endl;

	// 直接把构造string参数包往下传，直接用string参数包构造string
	// 这里达到的效果是push_back做不到的
	lt.emplace_back("111111111111");
	cout << "*********************************" << endl;


	list<pair<zyb::string, int>> lt1;//对象参数为多参数时的场景
	// 跟push_back一样
	// 构造pair + 拷贝/移动构造pair到list的节点中data上
	pair<zyb::string, int> kv("苹果", 1);

	lt1.emplace_back(kv);
	cout << "*********************************" << endl;
	// 跟push_back一样
	lt1.emplace_back(move(kv));
	cout << "*********************************" << endl;

	// 直接把构造pair参数包往下传，直接用pair参数包构造pair
	// 这⾥达到的效果是push_back做不到的
	lt1.emplace_back("苹果", 1);
	cout << "*********************************" << endl;
	return 0;
}

//=====================================================================================

// List.h
namespace zyb
{
	template<class T>
	struct ListNode
	{
		ListNode<T>* _next;
		ListNode<T>* _prev;
		T _data;
		ListNode(T&& data)
			:_next(nullptr)
			, _prev(nullptr)
			, _data(move(data))
		{}
		template <class... Args>
		ListNode(Args&&... args)
			: _next(nullptr)
			, _prev(nullptr)
			, _data(std::forward<Args>(args)...)
		{}
	};
	template<class T, class Ref, class Ptr>
	struct ListIterator
	{
		typedef ListNode<T> Node;
		typedef ListIterator<T, Ref, Ptr> Self;
		Node* _node;
		ListIterator(Node* node)
			:_node(node)
		{}
		// ++it;
		Self& operator++()
		{
			_node = _node->_next;
			return *this;
		}
		Self& operator--()
		{
			_node = _node->_prev;
			return *this;
		}
		Ref operator*()
		{
			return _node->_data;
		}
		bool operator!=(const Self& it)
		{
			return _node != it._node;
		}
	};
	template<class T>
	class list
	{
		typedef ListNode<T> Node;
	public:
		typedef ListIterator<T, T&, T*> iterator;
		typedef ListIterator<T, const T&, const T*> const_iterator;
		iterator begin()
		{
			return iterator(_head->_next);
		}
		iterator end()
		{
			return iterator(_head);
		}
		void empty_init()
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;
		}
		list()
		{
			empty_init();
		}
		void push_back(const T& x)
		{
			insert(end(), x);
		}
		void push_back(T&& x)
		{
			insert(end(), move(x));
		}
		iterator insert(iterator pos, const T& x)
		{
			Node* cur = pos._node;
			Node* newnode = new Node(x);
			Node* prev = cur->_prev;
			// prev newnode cur
			prev->_next = newnode;
			newnode->_prev = prev;
			newnode->_next = cur;
			cur->_prev = newnode;
			return iterator(newnode);
		}
		iterator insert(iterator pos, T&& x)
		{
			Node* cur = pos._node;
			Node* newnode = new Node(move(x));
			Node* prev = cur->_prev;
			// prev newnode cur
			prev->_next = newnode;
			newnode->_prev = prev;
			newnode->_next = cur;
			cur->_prev = newnode;
			return iterator(newnode);
		}
		template <class... Args>
		void emplace_back(Args&&... args)
		{
			insert(end(), std::forward<Args>(args)...);
		}
		// 原理：本质编译器根据可变参数模板生成对应参数的函数
		/*void emplace_back(string& s)
		{
			insert(end(), std::forward<string>(s));
		}
		void emplace_back(string&& s)
		{
			insert(end(), std::forward<string>(s));
		}
		void emplace_back(const char*&& s)
		{
			insert(end(), std::forward<const char*>(s));
		}
		*/
		template <class... Args>
		iterator insert(iterator pos, Args&&... args)
		{
			Node* cur = pos._node;
			Node* newnode = new Node(std::forward<Args>(args)...);
			Node* prev = cur->_prev;
			// prev newnode cur
			prev->_next = newnode;
			newnode->_prev = prev;
			newnode->_next = cur;
			cur->_prev = newnode;
			return iterator(newnode);
		}
	private:
		Node* _head;
	};
}

// Test.cpp
#include"List.h"
#include"string.h"
// emplace_back总体而言是更高效，推荐以后使用emplace系列替代insert和push系列
int main()
{
	zyb::list<zyb::string> lt;
	// 传左值，跟push_back一样，走拷贝构造
	zyb::string s1("111111111111");
	lt.emplace_back(s1);
	cout << "*********************************" << endl;
	// 右值，跟push_back一样，走移动构造
	lt.emplace_back(move(s1));
	cout << "*********************************" << endl;
	// 直接把构造string参数包往下传，直接用string参数包构造string
	// 这⾥达到的效果是push_back做不到的
	lt.emplace_back("111111111111");
	cout << "*********************************" << endl;
	zyb::list<pair<zyb::string, int>> lt1;
	// 跟push_back一样
	// 构造pair + 拷贝/移动构造pair到list的节点中data上
	pair<zyb::string, int> kv("苹果", 1);
	lt1.emplace_back(kv);
	cout << "*********************************" << endl;
	// 跟push_back一样
	lt1.emplace_back(move(kv));
	cout << "*********************************" << endl;
	////////////////////////////////////////////////////////////////////
	// 直接把构造pair参数包往下传，直接用pair参数包构造pair
	// 这⾥达到的效果是push_back做不到的
	lt1.emplace_back("苹果", 1);
	cout << "*********************************" << endl;
	return 0;
}